package com.rfid.reader;

import android.util.Log;

import com.rfid.api.GFunction;
import com.rfid.basetype.UINT16;
import com.rfid.basetype.UINT8;
import com.rfid.spec.ISO15693TagDataReport;
import com.rfid.spec.L0_APL;
import com.rfid.spec.L0_IdentifyDataIso15693;
import com.rfid.spec.SpecAIPInvenParamISO15693;
import com.rfid.spec.SpecAirProtocInvenParam;
import com.rfid.spec.SpecInvenParamSet;
import com.rfid.transport.BufferPack;

import java.util.Arrays;

public class DriverPC8001Net extends DriverPC8001 {
    private static final String Tag  = "DriverPC8001Net";
    char MSGTY_STARTRO = 'a';
    char MSGTY_GETREPORTANDSTA = 'e';
    char MSGTY_LOADFACTORYDEFAULT = 'g';

    private int m_AntennaSelected=0;
    private byte[] defAntennaIDs;
    public DriverPC8001Net() {
        this.mTranBuffer = new byte[51200];
        this.mTranRecvBuf = new BufferPack(51200);
        this.m_AntennaSelected = 0;
        this.defAntennaIDs = null;
        this.defaultInventoryTimeout = 30000;
        this.defAntennaIDs = new byte[GetAntennaInterfaceCount()];
        for (int i = 0; i < this.defAntennaIDs.length; i++) this.defAntennaIDs[i] = (byte) (i + 1);
    }

    private byte[] mTranBuffer;
    private BufferPack mTranRecvBuf;

    private char m_msgIdFeed =421;

    public BufferPack pbSend = new BufferPack(512);
    public BufferPack pbRecv = new BufferPack(51200);
    private byte[] mRecvDataBuf = new byte[51200];
    private byte[] mTranBufferOnce = new byte[256];
    private char GetMsgIdFeed() {
        char current = this.m_msgIdFeed;
        this.m_msgIdFeed = (char) (this.m_msgIdFeed + '\001' & 0xFFFF);
        if (this.m_msgIdFeed == '\000') this.m_msgIdFeed = '\001';
        return current;
    }
    public int SetAcessAntenna(int AntennaID) {
        this.m_syncLock.lock();
        this.pbSnd.flush();
        this.pbRecv.flush();
        char cmd = 1190;
        this.pbSnd.WriteData(cmd);
        this.pbSnd.WriteData((byte) (AntennaID & 0xFF));
        int iret = Transceive(cmd, this.pbSnd, this.pbRecv, 500L, false);
        if (iret != 0) {
            this.m_syncLock.unlock();
            return iret;
        }
        this.m_syncLock.unlock();
        iret = 0;
        return iret;
    }
    public int Transceive(char reqCmd, BufferPack snd, BufferPack recv, long timeout, boolean waitEndPacket) {
        UINT16 resp_cmd = new UINT16();
        UINT8 resp_sta = new UINT8();
        this.mTranRecvBuf.flush();
        Arrays.fill(this.mTranBuffer, (byte) 0);
        this.m_LastReaderErrCode = 0;
        this.m_transport.ioctrol(1);
        int iret = this.m_transport.send(snd.GetBuffer(), snd.getBufferLen(), 0);
        if (iret != 0) return iret;
        long curTime = System.currentTimeMillis();
        label33:
        while (true) {
            if (System.currentTimeMillis() - curTime > timeout) return -5;
            if (this.m_trancQuickExit) {
                this.m_trancQuickExit = false;
                return -35;
            }
              /*
            雷做了修改了，当接收到数据时不清空缓存
             */
            //this.mTranRecvBuf.flush();
            if (this.mTranRecvBuf.getBufferLen() <= 0) {
                this.mTranRecvBuf.flush();
            }
            while (true) {
                iret = this.m_transport.recv(this.mTranBuffer, Integer.valueOf(this.mTranBuffer.length), 0);
                if (iret > 0 || iret == -12) {
                    if (iret == -12) {
                        this.mTranRecvBuf.WriteData(this.mTranBuffer, 0, this.mTranBuffer.length);
                        continue;
                    }
                    this.mTranRecvBuf.WriteData(this.mTranBuffer, 0, iret);
                    continue label33;
                }
                break;
            }
            if (iret < 0) return iret;
            if (this.mTranRecvBuf.readable_length() >= 3) {
                this.mTranRecvBuf.ReadData(resp_cmd);
                this.mTranRecvBuf.ReadData(resp_sta);
                if (resp_cmd.getValue() != reqCmd) continue;
                recv.WriteData(this.mTranRecvBuf.GetBuffer(), 3, this.mTranRecvBuf.getBufferLen() - 3);
                if (waitEndPacket && this.mTranRecvBuf.readable_length() > 0) continue;
                break;
            }
        }
        if (resp_sta.getValue() != 0) {
            SetLastReaderErrCode(resp_sta.getValue());
            return -17;
        }
        return 0;
    }
    private void AddNewTag(byte antid, byte dsfid, byte[] uid) {
        long aip_type = 1L;
        long picc_type = 0L;
        L0_IdentifyDataIso15693 idf_data = new L0_IdentifyDataIso15693();
        System.arraycopy(uid, 0, idf_data.m_uid, 0, 8);
        L0_APL papl = this.m_L0RFID.GetAPL(1L);
        if (papl != null) picc_type = papl.IdentifyTag(idf_data);
        String strUID = "";
        String.format("%02X%02X%02X%02X%02X%02X%02X%02X", new Object[]{Byte.valueOf(uid[0]), Byte.valueOf(uid[1]), Byte.valueOf(uid[2]), Byte.valueOf(uid[3]), Byte.valueOf(uid[4]), Byte.valueOf(uid[5]), Byte.valueOf(uid[6]), Byte.valueOf(uid[7])});
        ISO15693TagDataReport pTDR = ISO15693TagDataReport.create();
        if (pTDR != null) {
            pTDR.m_AIPType = aip_type;
            pTDR.m_PICCType = picc_type;
            pTDR.m_AntID = antid;
            pTDR.m_Identifier = strUID;
            pTDR.m_dsfid = dsfid;
            System.arraycopy(uid, 0, pTDR.m_uid, 0, 8);
            OnInventoryPICCFound(pTDR);
        }
    }
    public int PICC_Inventory(byte AIType, byte[] AntennaIDs, int mTimeout, SpecInvenParamSet InvenParams)
    {
        this.m_syncLock.lock();
        this.pbSend.flush();
        if (mTimeout <= 0) mTimeout = this.defaultInventoryTimeout;
        ClearTDRManager();
        int iret = 0;
        SpecInvenParamSet pInvenParams = InvenParams;
        if (pInvenParams == null) pInvenParams = this.m_DefInvenParams;
        int mInvenTimeout = this.defaultInventoryTimeout;
        if (mTimeout > 0) mInvenTimeout = mTimeout;
        if (AntennaIDs == null) AntennaIDs = this.defAntennaIDs;
        if (AntennaIDs != null && AntennaIDs.length > 0)
        {
            int AntennaSelected = 0;
            for (int i = 0; i < AntennaIDs.length; i++)
                if (AntennaIDs[i] >= 1 && AntennaIDs[i] <= GetAntennaInterfaceCount())
                    AntennaSelected |= 1 << AntennaIDs[i] - 1;
            boolean AntennaConfigured = false;
            if (this.m_AntennaSelected == AntennaSelected) AntennaConfigured = true;
            if (!AntennaConfigured) {
                byte[] cfgblock = new byte[8];
                iret = ReadCfgBlock(1, cfgblock);
                if (iret != 0) return iret;
                cfgblock[1] = (byte) (AntennaSelected & 0xFF);
                cfgblock[2] = (byte) (AntennaSelected >> 8 & 0xFF);
                cfgblock[4] = (byte) (AntennaSelected >> 16 & 0xFF);
                cfgblock[5] = (byte) (AntennaSelected >> 24 & 0xFF);
                iret = WriteCfgBlock(1, cfgblock);
                if (iret != 0) return iret;
            }
            this.m_AntennaSelected = AntennaSelected;
        }

        SpecAirProtocInvenParam aipInvnParamSpec = pInvenParams.GetAirProtocolInvnParam(1L);
        UINT16 resp_cmd = new UINT16();
        UINT8 resp_sta = new UINT8((byte) 0);
        UINT16 resp_flag = new UINT16();
        if (aipInvnParamSpec != null) {
            SpecAIPInvenParamISO15693 aipInvParmISO15693 = (SpecAIPInvenParamISO15693) aipInvnParamSpec;
            byte InvenMode = 0;
            if (AIType != 1 && AIType == 2) InvenMode = (byte) (InvenMode | 0x1);
            if (aipInvParmISO15693.m_enableAFI) InvenMode = (byte) (InvenMode | 0x2);
            char cmd=510;
            this.pbSend.WriteData(cmd);
            this.pbSend.WriteData(InvenMode);
            if (aipInvParmISO15693.m_enableAFI) {
                this.pbSend.WriteData((byte) 1);
                this.pbSend.WriteData(aipInvParmISO15693.m_AFI);
            }
            iret=this.m_transport.send(this.pbSend.GetBuffer(),this.pbSend.getBufferLen(),0);
            if (iret != 0) {
                this.m_syncLock.unlock();
                return iret;
            }
            this.mTranRecvBuf.flush();
            //接收包
            long curTime = System.currentTimeMillis();
            label47:
            while (true) {
                if (System.currentTimeMillis() - curTime >= mTimeout) return -5;
                if (this.m_trancQuickExit) {
                    this.m_trancQuickExit = false;
                    return -35;
                }

                this.pbRecv.flush();
                boolean waitEndPacket =true;
                int offset=0;
                while (waitEndPacket)
                {
                    pbRecv.flush();
                    if (System.currentTimeMillis() - curTime >= mTimeout) break;
                    Arrays.fill(this.mTranBufferOnce, (byte) 0);
                    iret = this.m_transport.recv(this.mTranBufferOnce, Integer.valueOf(this.mTranBufferOnce.length), 0);
                    if (iret > 0 || iret == -12)
                    {
                         if (iret == -12)
                          {
                             this.pbRecv.WriteData(this.mTranBufferOnce, 0, this.mTranBufferOnce.length);
                              continue;
                          }
                         this.pbRecv.WriteData(this.mTranBufferOnce, 0, iret);
                         this.pbRecv.ReadData(resp_cmd);
                         this.pbRecv.ReadData(resp_sta);
                         this.pbRecv.ReadData(resp_flag);
                         CmdUDPResponse(resp_flag);
                         if (pbRecv.readable_length() <=0)
                         {
                             waitEndPacket =false;
                         }
                         else
                         {
                            while (this.pbRecv.readable_length() >0)
                            {
                                byte dsfid = 0;
                                byte[] uid = new byte[8];
                                byte antid = 1;
                                long aip_type = 1L;
                                long picc_type = 0L;
                                dsfid = this.pbRecv.ReadData();
                                this.pbRecv.ReadData(uid, 8);
                                GFunction.BytesReverse(uid, 8);
                                if (this.pbRecv.readable_length() > 0)
                                    antid = this.pbRecv.ReadData();
                                AddNewTag(antid,dsfid,uid);
                            }
                            // this.mTranRecvBuf.WriteData(this.pbRecv.GetBuffer(),offset,this.pbRecv.getBufferLen());

                         }
                     }
                }
                if (waitEndPacket)
                {
                    continue ;
                }else
                {
                    iret =0;
                    break ;

                }
                /*
                if (iret <0)break;
                //解析包
                this.mTranRecvBuf.WriteData(this.pbRecv.GetBuffer(),0,this.pbRecv.getBufferLen());
                if (this.mTranRecvBuf.readable_length() >= 3) {
                    this.mTranRecvBuf.ReadData(resp_cmd);
                    this.mTranRecvBuf.ReadData(resp_sta);
                    if (resp_cmd.getValue() != 510) continue;
                    if (this.mTranRecvBuf.readable_length() > 0)
                    {

                    }
                    break;
                }
                */
            }
        }
        this.m_syncLock.unlock();
        OnInventoryFinish();
        if (resp_sta.getValue() != 0) {
            if (resp_sta.getValue() != -32) {
                SetLastReaderErrCode(resp_sta.getValue());
                return -17;
            }
            return -21;
        }
        return iret;

    }
    /*
    UPD响应包
     */
    private int CmdUDPResponse(UINT16 flag)
    {
        this.m_syncLock.lock();
        this.pbSend.flush();
        char cmd=506;
        this.pbSend.WriteData(cmd);
        this.pbSend.WriteData(flag.getValue());
        int iret=this.m_transport.send(this.pbSend.GetBuffer(),this.pbSend.getBufferLen(),0);
        this.m_syncLock.unlock();
        return  iret;
    }


    private char crc16(byte[] pCrcData, int offset, int pLen)
    {
        int CRC = 61166;
        if (pLen==0)
        {
            return Character.MIN_VALUE;
        }
        for (int i = 0; i < pLen; i++) {
            CRC ^= pCrcData[i + offset]&0xFF;
            for (int j=0;j<8;j++)
            {
                if ((CRC &0x0001)!=0)
                {
                    CRC=(CRC>>1)^0x8408;
                }else {
                    CRC=(CRC>>1);
                }
            }
        }
        return  (char)CRC;
    }
    public boolean IsSupportNoiseDetect() {
        return true;
    }
}
